package com.thiswhyme.storage.core.platform;

import cn.hutool.core.io.IoUtil;
import com.obs.services.ObsClient;
import com.obs.services.model.*;
import com.thiswhyme.common.conststant.CommonConstant;
import com.thiswhyme.common.expection.BusinessException;
import com.thiswhyme.common.response.ResponseCode;
import com.thiswhyme.storage.core.FileStorage;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.CollectionUtils;

import java.io.InputStream;
import java.util.List;
import java.util.function.Consumer;

/**
 * @description: 华为云对象存储服务
 * @author: thiswhyme
 * @date: 2021/6/29
 */
@Slf4j
@AllArgsConstructor
public class HaweiObsStorage implements FileStorage {

    private String configKey;
    private String endpoint;
    private String accessKey;
    private String secretKey;
    private String bucketName;
    private String domain;

    private HaweiObsStorage() {

    }

    /**
     * 构建OBS
     * @return
     */
    public ObsClient getObs() {
        return new ObsClient(accessKey, secretKey, endpoint);
    }

    /**
     * 关闭
     * @param obs
     */
    public void close(ObsClient obs) {
        IoUtil.close(obs);
    }

    @Override
    public String platformCode() {
        return PlatformType.OBS.name() + CommonConstant.HYPHEN + configKey;
    }

    @Override
    public String upload(InputStream inputStream, String keyName) {
        ObsClient obs = getObs();
        try {
            // 简单文件上传, 支持上传0KB~5GB的对象
            PutObjectResult result = obs.putObject(bucketName, keyName, inputStream);
            log.info("文件上传成功，keyName：{}, 结果：{}", keyName, result.getStatusCode());
            return result.getEtag();
        } catch (Exception ex) {
            log.error("文件上传失败，keyName：{}", keyName, ex);
            throw new BusinessException(ResponseCode.SYSTEM_EXCEPTION.getCode(), "文件上传失败");
        } finally {
            close(obs);
        }
    }

    @Override
    public void download(String keyName, Consumer<InputStream> consumer) {
        ObsClient obs = getObs();
        try {
            ObsObject obsObject = obs.getObject(bucketName, keyName);
            try (InputStream in = obsObject.getObjectContent()) {
                consumer.accept(in);
            } catch (Exception e) {
                log.error("文件下载失败，keyName：{}", keyName, e);
                throw new BusinessException(ResponseCode.SYSTEM_EXCEPTION.getCode(), "文件下载失败");
            }
        } catch (Exception e) {
            log.error("文件下载失败，keyName：{}", keyName, e);
            throw new BusinessException(ResponseCode.SYSTEM_EXCEPTION.getCode(), "文件下载失败");
        } finally {
            close(obs);
        }
    }

    @Override
    public String fetchDownloadUrl(String keyName, Long expire) {
        String result;
        ObsClient obs = getObs();
        try {
            if(null == expire) {
                result = domain + "/" + keyName;
            } else {
                TemporarySignatureRequest request = new TemporarySignatureRequest(HttpMethodEnum.GET, 3600L);
                request.setBucketName(bucketName);
                request.setObjectKey(keyName);
                // 设置图片转码参数
//                Map<String,Object> queryParams = new HashMap<>(2);
//                queryParams.put("x-image-process", "image/resize,m_fixed,w_100,h_100/rotate,100");
//                request.setQueryParams(queryParams);

                TemporarySignatureResponse response = obs.createTemporarySignature(request);
                result = response.getSignedUrl();
            }
        } catch (Exception ex) {
            log.error("获取文件下载路径失败，keyName：{}", keyName, ex);
            throw new BusinessException(ResponseCode.SYSTEM_EXCEPTION.getCode(), "获取文件下载路径失败");
        } finally {
            close(obs);
        }
        return result;
    }

    @Override
    public void batchDelete(List<String> keyNames) {
        if (CollectionUtils.isEmpty(keyNames)) {
            return;
        }

        ObsClient obs = getObs();
        try {
            DeleteObjectsRequest request = new DeleteObjectsRequest(bucketName);
            for (String keyName : keyNames) {
                request.addKeyAndVersion(keyName);
            }
            DeleteObjectsResult result = obs.deleteObjects(request);
            log.info("文件批量删除成功，keyNames：{}, 结果：{}", keyNames, result.getStatusCode());
        } catch (Exception e) {
            log.error("文件批量删除失败，keyNames：{}", keyNames, e);
            throw new BusinessException(ResponseCode.SYSTEM_EXCEPTION.getCode(), "文件批量删除失败");
        } finally {
            close(obs);
        }
    }
}
